#ifndef _M_HOST_H_
#define _M_HOST_H_
#include"mq_binding.hpp"
#include"mq_exchange.hpp"
#include"mq_message.hpp"
#include"mq_queue.hpp"


namespace xiang11mq
{

//虚拟机管理操作类
class VirtualHost
{
public:

    using ptr = std::shared_ptr<VirtualHost>;
    VirtualHost(const std::string &hname, const std::string &basedir, const std::string &dbfile)
        :_host_name(hname)
        ,_emp(std::make_shared<ExchangeManager>(dbfile))
        ,_mqmp(std::make_shared<MsgQueueManager>(dbfile))
        ,_bmp(std::make_shared<BindingManager>(dbfile))
        ,_mmp(std::make_shared<MessageManager>(basedir))
    {
        //获取所有的队列信息 通过队列名称恢复历史消息      (mmp 在构造初始化的时候不会恢复历史消息 有了队列名字才会恢复历史消息)
        QueueMap qm = _mqmp->allQueues();
        for(auto &q : qm)
        {
            _mmp->initQueueMessage(q.first);
        }
    }
    //声明交换机
    bool declareExchange(const std::string &name, ExchangeType type, bool durable, bool auto_delete,
        const google::protobuf::Map<std::string, std::string> &args)
    {
        return _emp->declareExchange(name, type, durable, auto_delete, args);
    }
    //删除交换机
    void deleteExchange(const std::string &ename)
    {
        //删除交换机的时候 需要将交换机相关的绑定信息也删除掉 不能删绑定的队列
        _bmp->removeExchangeBindings(ename);
        return _emp->deleteExchange(ename);
    }
    //声明消息队列
    bool declareQueue(const std::string &qname, bool qdurable, bool qexclusive, bool qauto_delete
        ,const google::protobuf::Map<std::string, std::string> &qargs)
    {
        //初始化队列的消息句柄(消息的存储管理)
        _mmp->initQueueMessage(qname);
        //队列的创建
        return _mqmp->declareQueue(qname, qdurable, qexclusive, qauto_delete, qargs);
    }
    //删除消息队列
    void deleteQueue(const std::string &qname)
    {
        //删除的时候队列相关的数据有两个 队列的消息 队列的绑定信息
        _mmp->destroyQueueMessage(qname);
        _bmp->removeMsgQueueBindings(qname);
        return _mqmp->deleteQueue(qname);
    }
    //返回一个交换机
    Exchange::ptr selectExchange(const std::string &ename)
    {
        return _emp->selectExchange(ename);
    }
    //添加绑定
    bool bind(const std::string &ename, const std::string &qname, const std::string &key)
    {
        Exchange::ptr ep = _emp->selectExchange(ename);
        if(ep.get() == nullptr)
        {
            DLOG("虚拟机进行交换机—队列绑定失败, 交换机%s不存在", ename.c_str());
            return false;
        }
        MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
        if(mqp.get() == nullptr)
        {
            DLOG("虚拟机进行交换机—队列绑定失败, 队列%s不存在", qname.c_str());
            return false;
        }
        return _bmp->bind(ename, qname, key, ep->durable && mqp->durable);
    }
    //删除绑定
    void unBind(const std::string &ename, const std::string &qname)
    {
        return _bmp->unbind(ename, qname);
    }
    //获取交换机绑定数据
    MsgQueueBindingMap exchangeBindings(const std::string &ename)
    {
        return _bmp->getExchangeBingdings(ename);
    }
    //发布一条消息 从客户端收消息
    bool basicPublish(const std::string &qname, BasicProperties *bp, const std::string &body)
    {
        MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
        if(mqp.get() == nullptr)
        {
            DLOG("虚拟机进行发布消息失败, 队列%s不存在", qname.c_str());
            return false;
        }
        return _mmp->insert(qname, bp, body, mqp->durable);
    }
    //消费消息      推送消息到客户端
    MessagePtr basicConsume(const std::string &qname)
    {
        return _mmp->front(qname);
    }
    //确认消息
    bool basicAck(const std::string &qname, const std::string &msg_id)
    {
        return _mmp->ack(qname, msg_id);
    }
    //判断交换机是否存在
    bool existsExchange(const std::string &ename)
    {
        return _emp->exists(ename);
    }
    //判断消息队列是否存在
    bool existsQueue(const std::string &qname)
    {
        return _mqmp->exists(qname);
    }
    //返回所有队列信息
    QueueMap allQueues()
    {
        return _mqmp->allQueues();
    }
    //判断绑定信息是否存在
    bool existsBinding(const std::string &ename, const std::string &qname)
    {
        return _bmp->exists(ename, qname);
    }
    //清理
    void clear()
    {
        _emp->clear();
        _mqmp->clear();
        _bmp->clear();
        _mmp->clear();
    }

private:
    std::string _host_name;
    ExchangeManager::ptr _emp;
    MsgQueueManager::ptr _mqmp;
    BindingManager::ptr _bmp;
    MessageManager::ptr _mmp;
};


}

#endif